package com.example.spider.task;

import com.example.spider.proxy.core.ProxyInfo;
import com.example.spider.spider.RestSpider;
import com.example.spider.task.limit.LimitStrategy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import org.springframework.http.HttpMethod;

import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 爬虫任务
 *
 * @author lym
 */
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, defaultImpl = AbstractSpiderTask.class, visible = true
        , include = As.EXISTING_PROPERTY, property = "classForJson"
)
//JsonUtils.parseObject(JsonUtils.toJson(JsonUtils.parseObject(taskStr, Map.class, String.class, Object.class).get("task")), IpProxySpiderTask.class)
//@JsonSubTypes(
//        value = {
//                @JsonSubTypes.Type(value = IpProxySpiderTask.class, name = "IpProxySpiderTask"),
//                @JsonSubTypes.Type(value = CctvNewsDetailTask.class, name = "CctvNewsDetailTask")
//        }

//)
public interface Task<T> {

    Map<String, Class<? extends Task<?>>> subTypes = new ConcurrentHashMap<>(16);

    static void registerType(String name, Class<? extends Task<?>> clazz) {
        subTypes.put(name, clazz);
    }

    static void registerType(Class<? extends Task<?>> clazz) {
        subTypes.put(clazz.getSimpleName(), clazz);
    }

    /**
     * 爬取地址
     */
    String getUrl();

    /**
     * 请求方式
     *
     * @see HttpMethod
     */
    String getRequestMethod();

    /**
     * 请求参数
     */
    Object[] getParams();

    /**
     * 请求头
     */
    Map<String, String> getHeaders();

    /**
     * 请求头
     */
    Map<String, String> getResponseHeaders();

    /**
     * 请求头
     */
    Task<T> setResponseHeaders(Map<String, String> headers);

    /**
     * 使用特定字符集
     */
    default Charset getCharset() {
        return null;
    }


    Class<T> getResultType();

    /**
     * Cookies
     */
    //Map<String, String> getCookies();

    /**
     * 方便获取任务来源信息，谁、什么时候、为什么创建的
     */
    <X extends Task<?>> X getParent();

    /**
     * 方便获取任务来源信息，谁、什么时候、为什么创建的
     */
    default ProxyInfo getExceptedProxy() {
        return null;
    }

    /**
     * 方便获取任务来源信息，谁、什么时候、为什么创建的
     */
    default ProxyInfo getActuallyProxy() {
        return null;
    }

    LimitStrategy getLimitStrategy();

    // 结果

    <X extends Task<T>> X setRequestCost(long cost);

    int getRetryNum();

    <X extends Task<T>> X setRetryNum(int retryNum);

    boolean canRetry();

    String getIdempotentFilePath();

    default T onNoRetryEx(Exception e) {
        return RestSpider.retry(e, this);
    }

    T calculateIdempotentResult();

    default boolean supportCluster() {
        return true;
    }

}
